﻿using AutoMapper;
using JuCheap.Core.Data.Entity;
using JuCheap.Core.Infrastructure;
using JuCheap.Core.Infrastructure.Exceptions;
using JuCheap.Core.Infrastructure.Extentions;
using JuCheap.Core.IRepository;
using JuCheap.Core.IService.AppService;
using JuCheap.Core.Model;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace JuCheap.Core.Service.AppService
{
    /// <summary>
    /// 角色扩展服务
    /// </summary>
    public class RoleService : IRoleService
    {
        private readonly ISysRoleRepository _sysRoleRepository;
        private readonly ISysRoleMenuRepository _sysRoleMenuRepository;
        private readonly ISysCompanyRepository _sysCompanyRepository;
        private readonly IUnitWork _unitWork;
        private readonly IMapper _mapper;

        /// <summary>
        /// ctor
        /// </summary>
        public RoleService(IUnitWork unitWork, ISysRoleRepository sysRoleRepository, IMapper mapper,
            ISysRoleMenuRepository sysRoleMenuRepository,
            ISysCompanyRepository sysCompanyRepository)
        {
            _unitWork = unitWork;
            _sysRoleRepository = sysRoleRepository;
            _mapper = mapper;
            _sysRoleMenuRepository = sysRoleMenuRepository;
            _sysCompanyRepository = sysCompanyRepository;
        }

        /// <summary>
        /// 创建角色
        /// </summary>
        /// <param name="roleReq">角色请求信息</param>
        /// <returns>用户Id</returns>
        public async Task<string> CreateAsync(RoleCreateRequestDto roleReq)
        {
            if (await _sysRoleRepository.ExistsAsync(x => x.Name == roleReq.Name))
            {
                throw new BusinessException("角色名称重复");
            }
            var role = _mapper.Map<SysRole>(roleReq);
            var roleId = await _sysRoleRepository.InsertAsync(role);
            return roleId;
        }

        /// <summary>
        /// 修改用户
        /// </summary>
        /// <param name="roleReq">用户请求信息</param>
        /// <returns>用户Id</returns>
        public async Task<string> UpdateAsync(RoleEditRequestDto roleReq)
        {
            if (await _sysRoleRepository.ExistsAsync(x => x.Id != roleReq.Id && x.Name == roleReq.Name))
            {
                throw new BusinessException("角色名称重复");
            }

            var role = await _sysRoleRepository.FindAsync(roleReq.Id);
            _mapper.Map(roleReq, role);
            
            await _sysRoleRepository.UpdateAsync(role);
            return role.Id;
        }

        /// <summary>
        /// 角色菜单设置
        /// </summary>
        /// <param name="roleMenuReq"></param>
        /// <returns></returns>
        public async Task SetMenusAsync(RoleMenuSetRequestDto roleMenuReq)
        {
            //删除以前的数据
            await _sysRoleMenuRepository.DeleteAsync(x => x.RoleId == roleMenuReq.RoleId);
            //重新添加数据
            var list = roleMenuReq.MenuIds.Select(x => new SysRoleMenu
            {
                RoleId = roleMenuReq.RoleId,
                MenuId = x
            }).ToList();
            await _sysRoleMenuRepository.BatchInsertAsync(list);
        }

        /// <summary>
        /// 获取角色拥有的菜单Id集合
        /// </summary>
        /// <param name="roleId">角色Id</param>
        /// <returns></returns>
        public async Task<IEnumerable<string>> GetRoleMenuIdsAysnc(string roleId)
        {
            return await _sysRoleMenuRepository.Queryable().Where(x => x.RoleId == roleId).Select(x => x.MenuId).ToListAsync();
        }

        /// <summary>
        /// 角色分页扩展方法
        /// </summary>
        /// <param name="filter">基础分页参数</param>
        /// <returns></returns>
        public async Task<PagedResult<SysRoleDto>> QueryPagesAsync(SysRoleFilter filter)
        {
            var query = from role in _sysRoleRepository.Queryable()
                        join company in _sysCompanyRepository.Queryable() on role.CompanyId equals company.Id
                        select new SysRoleDto
                        {
                            Id = role.Id,
                            Name = role.Name,
                            Code = role.Code,
                            Remark = role.Remark,
                            CompanyName = company.CompanyName,
                            CreateTime = role.CreateTime
                        };
            query = query.WhereIf(filter.Name.IsNotBlank(), x => x.Name.Contains(filter.Name))
                .WhereIf(filter.Remark.IsNotBlank(), x => x.Remark.Contains(filter.Remark));

            return await query.QueryPagesAsync(filter);
        }
    }
}
